package cn.ulc.socket.weapp.service.impl;

import cn.ulc.common.constant.PubDataConstant;
import cn.ulc.common.constant.enums.AvailableStatus;
import cn.ulc.common.constant.enums.DeletedStatus;
import cn.ulc.common.exception.PlatformException;
import cn.ulc.common.util.CalendarUtil;
import cn.ulc.socket.weapp.common.BaseService;
import cn.ulc.socket.weapp.model.dto.SignDTO;
import cn.ulc.socket.weapp.model.dto.SignSaveDTO;
import cn.ulc.socket.weapp.model.param.CouponExchangeSaveParam;
import cn.ulc.socket.weapp.service.SignServ;
import cn.ulc.store.dao.CouponDao;
import cn.ulc.store.dao.PubDataDao;
import cn.ulc.store.dao.sign.SignDao;
import cn.ulc.store.dao.sign.SignRecordDao;
import cn.ulc.store.dao.user.MemberDao;
import cn.ulc.store.dao.user.UserCouponDao;
import cn.ulc.store.entity.Company;
import cn.ulc.store.entity.Coupon;
import cn.ulc.store.entity.sign.Sign;
import cn.ulc.store.entity.sign.SignRecord;
import cn.ulc.store.entity.user.Member;
import cn.ulc.store.entity.user.UserCoupon;
import cn.ulc.store.entity.user.WeixinUser;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class SignServImpl extends BaseService implements SignServ {
    SignDao signDao;
    SignRecordDao recordDao;
    CouponDao couponDao;
    PubDataDao pubDataDao;
    MemberDao memberDao;
    UserCouponDao userCouponDao;
    @Override
    @Transactional
    public SignSaveDTO saveSign() {
        SignSaveDTO dto = new SignSaveDTO();
        WeixinUser loginUser = getCurrentUser();
        Company company = getCurrentCompany();
        Sign sign = signDao.findByUserId(loginUser.getId());
        if(sign==null) throw new PlatformException("获取签到信息失败!");
        String date = CalendarUtil.dateToString(new Date(),CalendarUtil.SDF_DEFAULT);
        BigDecimal i = new BigDecimal((int)(Math.random()*40)+10);
        BigDecimal amount = i.divide(new BigDecimal(100));
        dto.setAmount(amount);
        if((sign.getDays()+1)%15==0){   //每十五天多获取一次
            i = new BigDecimal((int)(Math.random()*40)+10);
            BigDecimal extraAmount = i.divide(new BigDecimal(100));
            dto.setExtraAmount(extraAmount);
            amount = amount.add(extraAmount);
        }
        SignRecord record = recordDao.findByDate(loginUser.getId(),date);
        if(record==null) {
            record = new SignRecord();
            record.setAmount(amount);
            record.setWxUserId(loginUser.getId());
            record.setDate(new Date());
            record.setCompanyId(company.getId());
        }else if(record.getStatus() == AvailableStatus.AVAILABLE){
            throw new PlatformException("本日已经签到");
        }
        setBaseInfo(record);
        record.setStatus(AvailableStatus.AVAILABLE);
        record.setAmount(amount);
        recordDao.save(record);

        setBaseInfo(sign);
        BigDecimal nowAmount = amount.add(sign.getAmount());
        sign.setAmount(nowAmount);
        sign.setDays(sign.getDays()+1);
        String lastDate = CalendarUtil.dateToString(CalendarUtil.afterDays(new Date(),-1),CalendarUtil.SDF_DEFAULT);
        SignRecord lastRecord = recordDao.findByDate(loginUser.getId(),lastDate);
        if(lastRecord!=null && lastRecord.getStatus() == AvailableStatus.AVAILABLE){
            sign.setContinuityDays(sign.getContinuityDays()+1);
        }else{
            sign.setContinuityDays(1);
        }
        sign.setWxUserId(loginUser.getId());
        sign.setCompanyId(company.getId());
        signDao.save(sign);
        return dto;
    }

    @Override
    public SignDTO findIndex() {
        SignDTO dto = new SignDTO();
        WeixinUser loginUser = getCurrentUser();
        Company company = getCurrentCompany();
        String date = CalendarUtil.dateToString(new Date(),CalendarUtil.SDF_DEFAULT);
        String startDate = CalendarUtil.dateToString(CalendarUtil.afterDays(new Date(),-14),CalendarUtil.SDF_DEFAULT);
        List<SignRecord> recordList = recordDao.findListByDate(loginUser.getId(),startDate,date);
        Date todayDate = CalendarUtil.beginDate(new Date());
        if(recordList.size()<15){
            for(int i = 0;i<15;i++){
                Date currentDate = CalendarUtil.afterDays(todayDate,-i);
                Optional<SignRecord> opt = recordList.stream().filter(m->m.getDate().compareTo(currentDate)==0).findAny();
                if(!opt.isPresent()){
                    SignRecord record = new SignRecord();
                    setBaseInfo(record);
                    record.setWxUserId(loginUser.getId());
                    record.setDate(currentDate);
                    record.setCompanyId(company.getId());
                    record.setStatus(AvailableStatus.FREEZE);
                    recordDao.save(record);
                    recordList.add(record);
                }
            }
        }
        Comparator<SignRecord> comparator = (h1, h2) -> h2.getDate().compareTo(h1.getDate());
        recordList.sort(comparator.reversed());
        Sign sign = signDao.findByUserId(loginUser.getId());
        SignRecord record = recordList.get(14);
        if(record.getStatus()==AvailableStatus.FREEZE && recordList.get(13).getStatus() == AvailableStatus.FREEZE){
            sign.setContinuityDays(0);
            signDao.save(sign);
        }
        String code = pubDataDao.findCodeByTypeAndName(PubDataConstant.DATA_TYPE_COUPON,"签到礼包");
        List<Coupon> couponList = couponDao.findListByType(company.getId(),code);
        dto.setSign(sign);
        dto.setRecordList(recordList);
        dto.setRecord(record);
        dto.setCouponList(couponList);
        return dto;
    }

    @Override
    @Transactional
    public Boolean saveSignFill(Long id) {
        WeixinUser loginUser = getCurrentUser();
        SignRecord record = recordDao.findOne(id);
        setBaseInfo(record);
        record.setStatus(AvailableStatus.AVAILABLE);
        recordDao.save(record);
        Sign sign = signDao.findByUserId(loginUser.getId());
        if(sign.getAmount().subtract(BigDecimal.ONE).compareTo(BigDecimal.ZERO)==-1) throw new PlatformException("余额不足!");
        sign.setAmount(sign.getAmount().subtract(BigDecimal.ONE));
        sign.setDays(sign.getDays()+1);
        List<SignRecord> recordList = recordDao.findListByStatus(loginUser.getId(),AvailableStatus.AVAILABLE);
        List<SignRecord> continuityList = new ArrayList<>();
        Date date = CalendarUtil.beginDate(new Date());
        Date lastDate = CalendarUtil.afterDays(date,-1);
        if(recordList.size()>0){
            if(recordList.get(0).getDate().compareTo(date)==0){//如果今天已经签到
                continuityList.add(recordList.get(0));
                recordList.remove(0);
            }
            if(recordList.get(0).getDate().compareTo(lastDate)==0){//如果昨天已经签到
                int len = recordList.size();
                for(int i = 0;i<len;i++){
                    if(recordList.get(i).getDate().compareTo(CalendarUtil.afterDays(lastDate,-i))==0){
                        continuityList.add(recordList.get(i));
                    }else{
                        break;
                    }
                }
            }
            sign.setContinuityDays(continuityList.size());
            signDao.save(sign);
        }
        return true;
    }

    @Override
    @Transactional
    public SignDTO saveCoupon(CouponExchangeSaveParam param) {
        SignDTO dto = new SignDTO();
        WeixinUser loginUser = getCurrentUser();
        Company company = getCurrentCompany();
        Coupon coupon = couponDao.findOne(param.getCouponId());
        if(coupon==null) throw new PlatformException("优惠券不存在!");
        if(param.getCouponNum() > 0 ){
            Member member = memberDao.findByWxUserId(loginUser.getId(),AvailableStatus.AVAILABLE);
            for(int i = 1;i<=param.getCouponNum();i++){
                UserCoupon userCoupon = new UserCoupon();
                userCoupon.setDeleted(DeletedStatus.UN_DELETED);
                userCoupon.setCouponId(coupon.getId());
                userCoupon.setIsFull(coupon.getIsFull());
                userCoupon.setFullAmount(coupon.getFullAmount());
                userCoupon.setUserScope(coupon.getUserScope());
                userCoupon.setGoodsId(coupon.getGoodsId());
                userCoupon.setGoodsTypeId(coupon.getGoodsTypeId());
                userCoupon.setAmount(coupon.getAmount());
                userCoupon.setIsUsed(false);
                String newCode = "C"+PubDataConstant.DATA_TYPE_COUPON+loginUser.getId();
                String maxCode = userCouponDao.findMaxCode(loginUser.getId(),newCode);
                Integer len = 13 - newCode.length();
                String num = "1";
                if(StringUtils.isNotBlank(maxCode)){
                    num =  (Integer.valueOf(maxCode.substring(newCode.length()))+1)+"";
                }
                len = len - num.length();
                for(int j = 0;j<len;j++){
                    newCode+="0";
                }
                userCoupon.setCode(newCode+num);
                userCoupon.setCompanyId(company.getId());
                userCoupon.setCouponId(coupon.getId());
                if(member!=null) userCoupon.setMemberId(member.getId());
                userCoupon.setStatus(PubDataConstant.COUPON_STATUS_NOT_START);
                userCoupon.setTitle(coupon.getTitle());
                userCoupon.setWxUserId(loginUser.getId());
                userCoupon.setBeginTime(new Date());
                if(!coupon.getIsForever() && coupon.getStartDate().compareTo(new Date())==1){
                    userCoupon.setBeginTime(coupon.getStartDate());
                }
                userCoupon.setIsForever(coupon.getIsForever());
                userCoupon.setRemark(coupon.getRemark());
                userCouponDao.save(userCoupon);
            }
            Sign sign = signDao.findByUserId(loginUser.getId());
            if(sign==null) throw new PlatformException("签到信息获取失败!");
            setBaseInfo(sign);
            BigDecimal num = new BigDecimal(param.getCouponNum().toString());
            BigDecimal amount = sign.getAmount().subtract(num.multiply(coupon.getAmount()));
            sign.setAmount(amount);
            signDao.save(sign);
            dto.setSign(sign);
        }
        return dto;
    }

    @Override
    public void executeJob() {
//        Company company = getCurrentCompany();
        List<SignRecord> signRecordList = new ArrayList<>();
        List<Sign> signList = signDao.findList();
        if(signList!=null && signList.size() >0){
            for(Sign sign:signList){
                SignRecord record = new SignRecord();
                setBaseInfo(record);
                record.setCompanyId(sign.getCompanyId());
                record.setWxUserId(sign.getWxUserId());
                record.setMemberId(sign.getMemberId());
                record.setStatus(AvailableStatus.FREEZE);
                signRecordList.add(record);
            }
            recordDao.saveAll(signRecordList);
        }
    }
}
